-
Notifications
You must be signed in to change notification settings - Fork 395
[WIP] *: support layers federation #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
a387cea to
f27ff17
Compare
|
@mtrmac I just like to understand how you feel about this, I know the code is broken and need a look of fixing around "UpdatedImage" and such |
mtrmac
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, well, if it is a needed feature supported by docker/distribution, we will need to support it, so what’s not to like?
I would, however, like to see a comprehensive documentation somewhere of what this is supposed to do and why and how. Right now this adds URLs without any documentation; is the semantics that these layers should not or must not be copied? Will they always be accessible without authentication? (Perhaps these things are already documented somewhere in docker/distribution?)
And it might be desirable to have tests for schema conversion before this lands, and tests for how schema conversion interacts with this, and perhaps also tests for interaction with containers/storage. This kind of change seems somewhat likely to break something without us noticing.
copy/copy.go
Outdated
| } | ||
| cl = copiedLayer{blobInfo: destInfo, diffID: diffID} | ||
| } else { | ||
| fmt.Fprintf(reportWriter, "Skipping foreign layer copy to %s\n", dest.Reference().Transport().Name()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still need to fill in info for manifestUpdates.{InformationOnly.,}LayerInfos and possibly for manifestUpdates.InformationOnly.LayerDiffIDs which is much more horrible.
Also we might want to record URLs for the newly created layers as well.
copy/copy.go
Outdated
| err error | ||
| ) | ||
| for _, url := range srcInfo.URLs { | ||
| resp, err = http.Get(url) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementing a specific transport like this in the generic copy code is weird. Why wouldn’t this be done by an ImageSource, perhaps through ImageSource.GetBlob(info types.BlobInfo)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In particular, does the access never need any authentication?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In particular, does the access never need any authentication?
answer to this is, sadly, we don't yet know, ongoing discussion at moby/moby#27961
Implementing a specific transport like this in the generic copy code is weird. Why wouldn’t this be done by an ImageSource, perhaps through ImageSource.GetBlob(info types.BlobInfo)?
makes sense
| // uploaded to the image destination, false otherwise. | ||
| func (d *ociImageDestination) CopyForeignLayers() bool { | ||
| return false | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this true for dir: but false for oci:? At a first glance it seems that the two should behave similarly.
types/types.go
Outdated
|
|
||
| // CopyForeignLayers returns true iff foreign layers in manifest should be actually | ||
| // uploaded to the image destination, false otherwise. | ||
| CopyForeignLayers() bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps ShouldCopyForeignLayers or SupportsForeignLayers or something; this reads like a command to copy them.
1f99fdc to
1bcf590
Compare
@mtrmac PTAL (skopeo PR containers/skopeo#249) |
c42f15a to
f7d5778
Compare
docker/docker_image_src.go
Outdated
| err error | ||
| ) | ||
| for _, url := range urls { | ||
| resp, err = http.Get(url) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should use the previously setup docker client to comply with containers/skopeo#250
f4bb04e to
488f068
Compare
|
ping @mtrmac anything else? |
488f068 to
537ea34
Compare
|
rebased |
mtrmac
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The highlights are authentication and the naming vs. semantics of SupportsForeignLayers.
Also, shouldn’t convertToManifestSchema1 refuse to convert images with federated URLs?
image/docker_schema2.go
Outdated
| return nil, fmt.Errorf("Internal error: neither src nor configBlob set in manifestSchema2") | ||
| } | ||
| stream, _, err := m.src.GetBlob(m.ConfigDescriptor.Digest) | ||
| stream, _, err := m.src.GetBlob(types.BlobInfo{Digest: m.ConfigDescriptor.Digest}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn’t this fully convert the descriptor, including URLs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the very least, Size should be -1, not 0.
| GetTargetManifest(digest string) ([]byte, string, error) | ||
| // GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown). | ||
| GetBlob(digest string) (io.ReadCloser, int64, error) | ||
| GetBlob(BlobInfo) (io.ReadCloser, int64, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the caller expected to fill in everything, in particular is Size required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(AFAICT we don’t need it, so this would be just a matter of documenting The Digest field is guaranteed to be provided; Size may be -1 just as we do for LayerInfos where this information comes from.)
docker/docker_image_src.go
Outdated
| return nil, 0, err | ||
| } | ||
|
|
||
| func getBlobSizeFromHeader(h string) int64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could get a http.Response and look up the Content-Length header itself. This works as well, but the FromHeader naming is a bit confusing, when this is just a decimal parser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also there is another parser of Content-Length in docker_image_dest.go which could be modified to call this.)
docker/docker_image_src.go
Outdated
| err error | ||
| ) | ||
| for _, url := range urls { | ||
| resp, err = s.c.makeRequestToResolvedURL("GET", url, nil, nil, -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know I asked about authentication; still, is this right?
This would, when pulling a foreign RHEL from docker.io, send the docker.io credentials to Red Hat.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, we just need the client w/o auth here because we may need auth certificates against the give foreign server. We may probably need a new method in the client to make calls w/o authentication but still honor cert-path and the like for the given server we're connecting to here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, using the certs but not sending any tokens/passwords is AFAICT safe.
Ultimately, we would need to decide where the tokens/passwords are configured, and whether that is a per-transport matter or something general, and so on, but if we don’t have any server needing this right now, let's get this merged first and worry about that later.
copy/copy.go
Outdated
| func copyLayer(dest types.ImageDestination, src types.ImageSource, srcInfo types.BlobInfo, | ||
| diffIDIsNeeded bool, canCompress bool, reportWriter io.Writer) (types.BlobInfo, string, error) { | ||
| srcStream, srcBlobSize, err := src.GetBlob(srcInfo.Digest) // We currently completely ignore srcInfo.Size throughout. | ||
| srcStream, srcBlobSize, err := src.GetBlob(srcInfo) // We currently completely ignore srcInfo.Size throughout. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the srcInfo.Size comment still accurate? (See also types.go)
copy/copy.go
Outdated
| ) | ||
| if !dest.SupportsForeignLayers() && len(srcLayer.URLs) != 0 { | ||
| destInfo = srcLayer | ||
| // TODO: diffID? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it happens, DiffIDs are, at least currently, needed only when converting from schema1, in which case src.LayerInfos will not have URLs because schema1 does not support them. So, luckily enough, we don’t need to be handling this; just add a check
if diffIDsAreNeeded {
return errors.New("getting DiffIDs for foreign layers is unimplemented") // and a comment explaining schema1
}
copy/copy.go
Outdated
| if !dest.SupportsForeignLayers() && len(srcLayer.URLs) != 0 { | ||
| destInfo = srcLayer | ||
| // TODO: diffID? | ||
| fmt.Fprintf(reportWriter, "Skipping foreign layer copy to %s\n", dest.Reference().Transport().Name()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably identify the blob by digest (and the Copying Blob message above should go into the else branch below).
types/types.go
Outdated
|
|
||
| // SupportsForeignLayers returns true iff foreign layers in manifest should be actually | ||
| // uploaded to the image destination, false otherwise. | ||
| SupportsForeignLayers() bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This naming is pretty confusing; this should return false exactly in the cases when the destination understands URLs.
As is, this is really ShouldConvertForeignLayersToBlobCopies :) Or perhaps keep the current semantics and call it AcceptsForeignLayerURLs?
| if len(l.URLs) != 0 { | ||
| om.Layers[i].MediaType = imgspecv1.MediaTypeImageLayerNonDistributable | ||
| } else { | ||
| om.Layers[i].MediaType = imgspecv1.MediaTypeImageLayer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I remember correctly the OCI discussion of URLs vs. MIME types, URLs means “pull from here” and a MIME type can be used to indicate “don’t push this”; if so, the OCI MIME type should be based on whether the Docker MIME type is a …rootfs.foreign.diff…, not on the presence of URLs.
Or is the semantics of URLs vs. MIME type different between Docker s2 and OCI?
537ea34 to
87cb0b5
Compare
|
@mtrmac updated and fixed your comments. PTAL |
87cb0b5 to
0dc9b44
Compare
|
rebased again. |
|
|
||
| // AcceptsForeignLayerURLs returns true iff foreign layers in manifest should be actually | ||
| // uploaded to the image destination, false otherwise. | ||
| AcceptsForeignLayerURLs() bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m sorry, I have suggested this exact wording and this is entirely my fault, but AcceptsForeignLayerURLs is the opposite of what the flag means: false = keep the BlobInfo with the URL, true = make a copy.
(Writing this out in case I am making another mistake.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I rework the comment here and swap true with false then right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
0dc9b44 to
b19dce0
Compare
|
@mtrmac updated and rebased |
|
I still see |
b19dce0 to
60ff2bc
Compare
How about now? I swapped all occurrences I guess |
|
Missing the use in |
60ff2bc to
d1103c5
Compare
yep, sorry, forget me, I updated the use in copy as well. |
|
lgtm thanks @mtrmac sorry for the back and forth |
|
I'll fix the skopeo PR before merging here, stay tuned |
Signed-off-by: Antonio Murdaca <[email protected]>
d1103c5 to
d54f115
Compare
|
containers/skopeo#249 is good to go as well, merging here |
Add a CONTRIBUTING.md file
@mtrmac PTAL
More information available at moby/moby#27961
Signed-off-by: Antonio Murdaca [email protected]